﻿#include "TestMemPool.h"
#include "CStaticMemPool.h"
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <iostream>

TestMemPool::TestMemPool()
{
	this->m_obj = new stObj[__OBJ_NUM];
	this->m_obj2 = new stObj[__OBJ_NUM];

	assert(this->m_obj);
	assert(this->m_obj2);

	this->ResetSize();
}

TestMemPool::~TestMemPool()
{
	delete[] this->m_obj;
	delete[] this->m_obj2;
}

void TestMemPool::Alloc(int type, bool pool)
{
	size_t num = 1;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
		};
		break;
	default:
		return;
	}

	size_t pos = 0;
	for(; pos < __OBJ_NUM; ++pos)
	{
		/// 每num个元素执行一次
		if(pos % num == 0)
		{
			/// 占有内存，先删除
			if(this->m_obj[pos].addr)
			{
				if(pool)
				{
					bool ret = CStaticMemPool::GetInstance().Deallocate(this->m_obj[pos].addr, this->m_obj[pos].size);
					assert(ret);
					if(ret)
					{
						this->m_obj[pos].addr = NULL;
					}
					else
					{
						std::cout << "Error in Deallocate" << std::endl;
						return;
					}
				}
				else
				{
					free(this->m_obj[pos].addr);
					this->m_obj[pos].addr = NULL;
				}
				return ;
			}

			/// 分配内存
			if(pool)
			{
				this->m_obj[pos].addr = CStaticMemPool::GetInstance().Allocate(this->m_obj[pos].size);
				assert(this->m_obj[pos].addr);
				if(!this->m_obj[pos].addr)
				{
					std::cout << "Error in Allocate" << std::endl;
					return;
				}
			}
			else
			{
				this->m_obj[pos].addr = malloc(this->m_obj[pos].size);
				assert(this->m_obj[pos].addr);
				if(!this->m_obj[pos].addr)
				{
					std::cout << "Error in malloc" << std::endl;
					return;
				}
			}
		}
	}
}

void TestMemPool::Alloc2(int type, bool pool)
{
	size_t num = 1;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
		};
		break;
	default:
		return;
	}

	size_t pos = 0;
	for(; pos < __OBJ_NUM; ++pos)
	{
		/// 每num个元素执行一次
		if(pos % num == 0)
		{
			/// 占有内存，先删除
			if(this->m_obj2[pos].addr)
			{
				if(pool)
				{
					bool ret = CStaticMemPool::GetInstance().Deallocate(this->m_obj2[pos].addr, this->m_obj2[pos].size);
					assert(ret);
					if(ret)
					{
						this->m_obj2[pos].addr = NULL;
					}
					else
					{
						std::cout << "Error in Deallocate2" << std::endl;
						return;
					}
				}
				else
				{
					free(this->m_obj2[pos].addr);
					this->m_obj2[pos].addr = NULL;
				}
			}

			/// 分配内存
			if(pool)
			{
				this->m_obj2[pos].addr = CStaticMemPool::GetInstance().Allocate(this->m_obj2[pos].size);
				assert(this->m_obj2[pos].addr);
				if(!this->m_obj2[pos].addr)
				{
					std::cout << "Error in Allocate2" << std::endl;
					return;
				}
			}
			else
			{
				this->m_obj2[pos].addr = malloc(this->m_obj2[pos].size);
				assert(this->m_obj2[pos].addr);
				if(!this->m_obj2[pos].addr)
				{
					std::cout << "Error in malloc2" << std::endl;
					return;
				}
			}
		}
	}
}

void TestMemPool::Dealloc(int type, bool pool)
{
	size_t num = 1;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
		};
		break;
	default:
		return;
	}

	size_t pos = 0;
	for(; pos < __OBJ_NUM; ++pos)
	{
		/// 每num个元素执行一次
		if(pos % num == 0)
		{
			/// 占有内存，删除
			if(this->m_obj[pos].addr)
			{
				if(pool)
				{
					bool ret = CStaticMemPool::GetInstance().Deallocate(this->m_obj[pos].addr, this->m_obj[pos].size);
					assert(ret);
					if(ret)
					{
						this->m_obj[pos].addr = NULL;
					}
					else
					{
						std::cout << "Error in Deallocate" << std::endl;
						return;
					}
				}
				else
				{
					free(this->m_obj[pos].addr);
					this->m_obj[pos].addr = NULL;
				}
			}
		}
	}
}

void TestMemPool::Dealloc2(int type, bool pool)
{
	size_t num = 1;

	switch(type)
	{
	case __TYPE_RAND:
		{
			/// 1 ~ 5
			num = (rand() % 5) + 1;
		}
		break;
	case __TYPE_EVERY:
		{
			num = 1;
		};
		break;
	default:
		return;
	}

	size_t pos = 0;
	for(; pos < __OBJ_NUM; ++pos)
	{
		/// 每num个元素执行一次
		if(pos % num == 0)
		{
			/// 占有内存，删除
			if(this->m_obj2[pos].addr)
			{
				if(pool)
				{
					bool ret = CStaticMemPool::GetInstance().Deallocate(this->m_obj2[pos].addr, this->m_obj2[pos].size);
					assert(ret);
					if(ret)
					{
						this->m_obj2[pos].addr = NULL;
					}
					else
					{
						std::cout << "Error in Deallocate2" << std::endl;
						return;
					}
				}
				else
				{
					free(this->m_obj2[pos].addr);
					this->m_obj2[pos].addr = NULL;
				}
			}
		}
	}
}

void TestMemPool::ViolenceTest(size_t n, int type, bool pool)
{
	size_t pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Dealloc(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc2(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Dealloc2(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Dealloc(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc2(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Alloc(type, pool);
		this->Dealloc2(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

	pos = 0;
	for(; pos < n; ++pos)
	{
		this->Dealloc(type, pool);
		this->Dealloc2(type, pool);
	}
	CStaticMemPool::GetInstance().PrintMemBlock();

}

void TestMemPool::ResetSize()
{
	/// 设置内存分配的大小
	size_t pos = 0;
	std::cout << "m_obj：" << std::endl;

	for(; pos < __OBJ_NUM; ++pos)
	{
		this->m_obj[pos].size = rand() % CStaticMemPool::__MAX_BYTES_ + 1;
#ifdef _RESET_SIZE
		std::cout << this->m_obj[pos].size << "  ";
#endif
	}

	pos = 0;
	std::cout << "m_obj2：" << std::endl;

	for(; pos < __OBJ_NUM; ++pos)
	{
		this->m_obj2[pos].size = rand() % CStaticMemPool::__MAX_BYTES_ + 1;
#ifdef _RESET_SIZE
		std::cout << this->m_obj2[pos].size << "  ";
#endif
	}
}